|
|
|
|
|
|
|
Figure S30-1:
Passing the SHFILEOPSTRUCT structure to an API function |
|
|
|
|
|
|
|
|
the contents of those fields is likely to cause a memory exception. |
|
|
|
|
|
|
|
|
What happens when a dynamic string is inside a structure that is passed as a parameter? Visual Basic creates a temporary structure and replaces the BSTR field with an ANSI BSTR string. Figure S30-1 illustrates this for the first three fields in the SHFILEOPSTRUCT structure, where the pFrom field contains two file names, F1 and F2. |
|
|
|
|
|
|
|
|
As you can see from this illustration, when the function is called, the pFrom field points to an ANSI string that contains the two file names separated by NULL characters, with two NULL termination characters at the end of the string. This is exactly what the API function expects to see, so the only way that this could cause a problem is if the function were somehow modifying the contents of this structure. Is this possible? |
|
|
|
|
|
|
|
|
The string in the structure is defined in the C declaration as an LPCSTR (LP = Long (far) Pointer, C = Constant, STR = String). The Constant code indicates that the API function will not change the value of the string or the field within the structure. Based on the declaration and documentation, it is safe and correct to use dynamic strings as shown in this example. Nevertheless, it fails. |
|
|
|
|
|
|
|
|
Structure Alignment Revisited |
|
|
|
|
|
|
|
|
Let's take a moment to look closely at how the fields in the SHFILEOPSTRUCT structure are laid out in memory. If you look at the start of the shellapi.h header file, you'll see the following line: |
|
|
|
|
|
|
|
|
which turns on single-byte packing. That means that the structure will appear in memory as shown in Figure S30-2. Each field of data in the structure appears immediately after its predecessor in memory. |
|
|
|
|
|
|
|
|
But Visual Basic only uses single-byte packing when writing data to disk files. When structures are passed to API functions, Visual Basic uses natural alignment rules, meaning that each field appears at a memory location divisible by the size of the field. Therefore, 32-bit variables appear at a byte address divisible by 4, |
|
|
|
|
|